<?php
/**
* Joomla! 1.5 Content links filter 
* based on BBCodeParser Links.php by Stijn de Reede  <sjr@gmx.co.uk>
*
* yvBBCode - BBCode Plugin, developed for Joomla! 1.5
* 
* @version		$Id: ContentLinks.php 0004 2008-10-25 00:00:00Z yvolk $
* @package		yvBBCodePlugin
* @author	  yvolk (Yuri Volkov) <http://yurivolkov.com>
* @copyright	2007-2008 yvolk (Yuri Volkov), http://yurivolkov.com. All rights reserved.
* @license		GNU/GPL, see LICENSE.php
*/

// Required for function ContentIDToURL	
require_once (JPATH_SITE.DS.'includes'.DS.'application.php' );
require_once (JPATH_SITE.DS.'components'.DS.'com_content'.DS.'helpers'.DS.'route.php');

/**
 *
 */
class HTML_BBCodeParser_Filter_ContentLinks extends HTML_BBCodeParser_Filter
{

    /**
     * An array of tags parsed by the engine
     *
     * @access   private
     * @var      array
     */
    var $_definedTags = array(
        'contentid' => array(
            'htmlopen'  => 'a',
            'htmlclose' => 'a',
            'allowed'   => 'none^img',
            'attributes'=> array('contentid' => 'href=%2$s%1$s%2$s')
        ),
        // the same, but open in new window
        'contentidn' => array(
            'htmlopen'  => 'a target=\'_blank\'',
            'htmlclose' => 'a',
            'allowed'   => 'none^img',
            'attributes'=> array('contentidn' => 'href=%2$s%1$s%2$s')
        )
    );


    /**
     * Executes statements before the actual array building starts
     *
     * This method should be overwritten in a filter if you want to do
     * something before the parsing process starts. This can be useful to
     * allow certain short alternative tags which then can be converted into
     * proper tags with preg_replace() calls.
     * The main class walks through all the filters and and calls this
     * method if it exists. The filters should modify their private $_text
     * variable.
     *
     * @return   none
     * @access   private
     * @see      $_text
     * @author   Stijn de Reede <sjr@gmx.co.uk>
     */
    function _preparse()
    {
        $options = PEAR::getStaticProperty('HTML_BBCodeParser', '_options');
        $o = $options['open'];
        $c = $options['close'];
        $oe = $options['open_esc'];
        $ce = $options['close_esc'];

        //$this->_preparsed = $this->_text;
        //$pattern1 = array("!".$oe."contentid(".$ce."|\s.*".$ce.")(.*)".$oe."/contentid".$ce."!Ui");
        //$replace1 = array( $o."contentid=\\2\\1\\2".$o."/contentid".$c);
        //$pp = preg_replace($pattern1, $replace1, $this->_text);
        $pp = $this->_text;

        //$pattern2 = "!".$oe."contentid=([0-9]+)([^\s\[\]]*)".$ce."!i";
        //$pattern2 = "!".$oe."contentid=([0-9]+)([^\s\[\]]*)".$ce."([^\s\[\]]*)".$oe."/contentid".$ce."!i";
        $pattern2 = "!".$oe."contentid=([^\[\]]*)".$ce."([^\[\]]*)".$oe."/contentid".$ce."!i";
        $this->_preparsed = preg_replace_callback($pattern2, array($this, 'replaceContentid'), $pp);
        //$this->_preparsed = $pp;
    }
    
    function replaceContentid($matches) {
			global $mainframe;

      $options = PEAR::getStaticProperty('HTML_BBCodeParser','_options');
      $o = $options['open'];
      $c = $options['close'];
      $debug = false;

    	$id = $matches[1];
    	$text = $matches[2];

    	$urlContent = $this->ContentIDToURL($id, false);
    
      $ret = '';
      if ($debug) {
        $ret .= '<br>start';
        $ret .= '; Route="' .  $urlContent . '" ';
        $ret .= '; matchers="' . preg_replace('([\[\]]+)', '*', print_r($matches, true)) . '" ';
        $ret .= '<br>replaced with: ';
      }  
      if ($urlContent == '') {
      	$ret .= $text;
      } else {
					if ($mainframe->isAdmin()) {
		      	$ret .= $o .'contentidn="'.$urlContent. '"' . $c . $text .$o.'/contentidn'.$c;
					} else {
			      //$ret .= $o .'contentid='.$urlContent. $c . $text .$o.'/contentid'.$c;
		      	//$ret .= $o .'url='.$urlContent. $c . $text .$o.'/url'.$c;
		      	$ret .= $o .'contentid="'.$urlContent. '"' . $c . $text .$o.'/contentid'.$c;
					}
      }
      if ($debug) {
        $ret .= '<br>end<br>';
      }  
      return $ret;
    }

	 /* Build URL to the Article by it's ID, taking SEF settings, 
	 * security for UserID etc. into account 
   * @version		$Id: ContentIDToURL 0007 2008-10-19 00:00:00Z yvolk $
	 * @author	  yvolk (Yuri Volkov) <http://yurivolkov.com>
   * Based on code from getList function of 'modules/mod_latestnews/helper.php'
	 * It is very strange, that Joomla didn't have such function yet...
	 * It has now :-), but the implementation is far from ideal...
	 */    
  function ContentIDToURL($id_in, $pathonly = true, $UserID = null, $ShowUnpublished = false) {
    $debug = false; // ($id_in == 421);
    $message = '';
  	$id = (integer) $id_in;
  	$url = '';
  	if ($id > 0) {
			global $mainframe;
	
			$db			=& JFactory::getDBO();
			$user		=& JFactory::getUser($UserID);
			$userId		= (int) $user->get('id');
			$aid		= $user->get('aid', 0);
	
			$contentConfig = &JComponentHelper::getParams( 'com_content' );
			$access		= !$contentConfig->get('shownoauth');
			$where = '';
			if ($debug) {
			  $message .= 'articleid=' . $id_in . '<br/>';
			}
			if (!$ShowUnpublished) {
				$nullDate	= $db->getNullDate();
				jimport('joomla.utilities.date');
				$date = new JDate();
				$now = $date->toMySQL();
		
				$where		= 'a.state = 1'
					. ' AND ( a.publish_up = '.$db->Quote($nullDate).' OR a.publish_up <= '.$db->Quote($now).' )'
					. ' AND ( a.publish_down = '.$db->Quote($nullDate).' OR a.publish_down >= '.$db->Quote($now).' )'
					;
			}		

			if (!empty($where)) {
				$where .= ' AND ';
			}			
			$where .= 'a.id = ' . $id;
			if ($access) {
				$where .= ' AND a.access <= ' .(int) $aid 
				. ' AND ((cc.access <= ' .(int) $aid. ') OR cc.id IS NULL)' 
				. ' AND ((s.access <= ' .(int) $aid . ') OR s.id IS NULL)';
			}	
			if (!$ShowUnpublished) {
				$where .= ' AND ((s.published = 1) OR (s.id IS NULL))' .
					' AND ((cc.published = 1) OR (cc.id IS NULL))';
			}		
	
			// Just like it is done in 'components/com_content/models/article.php'
			$query = 'SELECT a.sectionid,' .
				' CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias) ELSE a.id END as slug,'.
				' CASE WHEN CHAR_LENGTH(cc.alias) THEN CONCAT_WS(":", cc.id, cc.alias) ELSE cc.id END as catslug'.
				' FROM #__content AS a' .
				' LEFT JOIN #__categories AS cc ON cc.id = a.catid' .
				' LEFT JOIN #__sections AS s ON s.id = a.sectionid' .
				' WHERE '. $where;
				
			$db->setQuery($query);
			$row = $db->loadObject();
			if (!is_null($row)) {
			  if ($debug) {
			    $message .= 'slug=' . $row->slug . '<br/>';
			  }
				// Just like it is done in 'components/com_content/views/article/view.html.php'
				$url = JRoute::_(ContentHelperRoute::getArticleRoute($row->slug, $row->catslug, $row->sectionid));
				
				// This hack is needed for the backend.
				// Oherwise the link would lead to the Article manager...
				if ( (!$pathonly) || $mainframe->isAdmin()) {
					$base = JURI::root();
				  if ((substr($base, -1, 1) == '/') && (substr($url, 0, 1) == '/')) {
				  	// Avoid '/' duplication				  
				    $url = substr($url, 1);
				  }
					$url = $base . $url;
				}
			}	else {
			  if ($debug) {
			    $message .= 'row is null<br/>';
					$message .= $this->printDbErrors($db);
			  }
			}
  	}
  	if ($message) {
  	  global $mainframe;
			$mainframe->enqueueMessage($message, 'notice');
  	}
    return $url;
  }

}
?>